package com.yunda.nebula.gateway.beandefine;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.util.*;

/**
 * \* User: wei.zhang
 * \* Date: 2019/11/12 15:30
 * \* Description:
 * \
 */
//@Service
public class LocalRouteDefinitionRepository implements RouteDefinitionRepository, InitializingBean {

    private Map<String,RouteDefinition> map = new HashMap<>();


    private RouteDefinition getRouteDefinition(){
        RouteDefinition routeDefinition = new RouteDefinition();
        PredicateDefinition predicateDefinition = new PredicateDefinition();
        Map<String, String> predicateParams = new HashMap<>(8);
        Map<String, String> filterParams = new HashMap<>(8);
        FilterDefinition filterDefinition = new FilterDefinition();
        URI uri = UriComponentsBuilder.fromUriString("lb://gemini-admin").build().toUri();
// 名称是固定的，spring gateway会根据名称找对应的PredicateFactory
        predicateDefinition.setName("Path");
        predicateParams.put("pattern", "/gemini/admin/**");
        predicateDefinition.setArgs(predicateParams);
// 名称是固定的，spring gateway会根据名称找对应的FilterFactory
        filterDefinition.setName("TokenAuth");
//// 每秒最大访问次数
//        filterParams.put("redis-rate-limiter.replenishRate", "2");
//// 令牌桶最大容量
//        filterParams.put("redis-rate-limiter.burstCapacity", "3");
//// 限流策略(#{@BeanName})
//        filterParams.put("key-resolver", "#{@hostAddressKeyResolver}");
// 自定义限流器(#{@BeanName})
//filterParams.put("rate-limiter", "#{@redisRateLimiter}");
        filterDefinition.setArgs(filterParams);
        routeDefinition.setPredicates(Arrays.asList(predicateDefinition));
        routeDefinition.setFilters(Arrays.asList(filterDefinition));
        routeDefinition.setUri(uri);
        return routeDefinition;

    }

    private BeanDefineProvider beanDefineProvider;
    @Override
    public Flux<RouteDefinition> getRouteDefinitions() {
        List<RouteDefinition> routeDefinitions = new ArrayList<>();
        routeDefinitions.addAll(beanDefineProvider.provider());
        return Flux.fromIterable(routeDefinitions);
    }

    @Override
    public Mono<Void> save(Mono<RouteDefinition> route) {
        route.flatMap(routeDefinition->{
            System.out.println( routeDefinition.getId());
            beanDefineProvider.add(routeDefinition);
//            map.remove(routeDefinition.getId());
            //routeDefinition.getId();
            return Mono.empty();
        });
        return  Mono.empty();
    }

    @Override
    public Mono<Void> delete(Mono<String> routeId) {
        String id = routeId.block();
        beanDefineProvider.remove(id);
        return Mono.empty();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        RouteDefinition routeDefinition = getRouteDefinition();
        map.put(routeDefinition.getId(),routeDefinition);
    }
}
